package com.devenv.common.plugin;

import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import java.util.List;
import java.util.Map;

/**
 * 通知服务接口
 * <p>
 * 定义了统一的通知服务接口，支持多种通知方式的插件化扩展。
 * 包括邮件通知、短信通知、站内消息、推送通知等。
 * </p>
 * 
 * @author DevEnv OpenSource Team
 * @version 1.0.0
 * @since 1.0.0
 */
public interface INotificationService {

    /**
     * 获取通知服务的名称
     * <p>
     * 用于标识不同的通知服务，如："email", "sms", "push", "internal"等
     * </p>
     * 
     * @return 通知服务名称，不能为null
     */
    @NonNull
    String getName();

    /**
     * 获取通知服务的显示名称
     * <p>
     * 用于在UI界面显示给用户，如："邮件通知", "短信通知", "推送通知"等
     * </p>
     * 
     * @return 通知服务显示名称，不能为null
     */
    @NonNull
    String getDisplayName();

    /**
     * 获取支持的通知类型
     * <p>
     * 返回该服务支持的通知类型列表
     * </p>
     * 
     * @return 支持的通知类型列表，如["INFO", "WARNING", "ERROR"]，不能为null
     */
    @NonNull
    List<NotificationType> getSupportedTypes();

    /**
     * 检查通知服务是否可用
     * <p>
     * 用于检查通知服务是否正常工作，包括网络连接、配置信息等
     * </p>
     * 
     * @return true表示可用，false表示不可用
     */
    boolean isAvailable();

    /**
     * 发送单个通知
     * <p>
     * 向指定接收者发送通知消息
     * </p>
     * 
     * @param notification 通知内容，不能为null
     * @return 发送结果，包含发送状态和消息ID等，不能为null
     * @throws NotificationException 发送过程中出现错误时抛出
     */
    @NonNull
    SendResult sendNotification(@NonNull Notification notification) throws NotificationException;

    /**
     * 批量发送通知
     * <p>
     * 向多个接收者发送相同的通知消息
     * </p>
     * 
     * @param notification 通知内容，不能为null
     * @param recipients 接收者列表，不能为null或空
     * @return 批量发送结果，包含每个接收者的发送状态，不能为null
     * @throws NotificationException 发送过程中出现错误时抛出
     * @since 1.0.0
     */
    @NonNull
    BatchSendResult sendBatchNotification(@NonNull Notification notification, 
                                        @NonNull List<String> recipients) throws NotificationException;

    /**
     * 发送模板通知
     * <p>
     * 使用预定义的模板发送通知，支持参数替换
     * </p>
     * 
     * @param templateId 模板ID，不能为null或空字符串
     * @param recipient 接收者，不能为null或空字符串
     * @param parameters 模板参数，可以为null
     * @return 发送结果，不能为null
     * @throws NotificationException 发送过程中出现错误时抛出
     * @since 1.0.0
     */
    @NonNull
    SendResult sendTemplateNotification(@NonNull String templateId, 
                                      @NonNull String recipient, 
                                      @Nullable Map<String, Object> parameters) throws NotificationException;

    /**
     * 查询发送状态
     * <p>
     * 查询指定通知的发送状态和详情
     * </p>
     * 
     * @param messageId 消息ID，不能为null或空字符串
     * @return 发送状态，消息不存在时返回null
     * @throws NotificationException 查询过程中出现错误时抛出
     * @since 1.0.0
     */
    @Nullable
    SendStatus getMessageStatus(@NonNull String messageId) throws NotificationException;

    /**
     * 撤回通知
     * <p>
     * 撤回已发送的通知（如果支持）
     * </p>
     * 
     * @param messageId 消息ID，不能为null或空字符串
     * @return true表示撤回成功，false表示撤回失败或不支持撤回
     * @throws NotificationException 撤回过程中出现错误时抛出
     * @since 1.0.0
     */
    boolean recallNotification(@NonNull String messageId) throws NotificationException;

    /**
     * 获取服务配置信息
     * <p>
     * 返回当前通知服务的配置状态，用于系统监控和故障排查
     * </p>
     * 
     * @return 配置信息的键值对，不包含敏感信息，不能为null
     * @since 1.0.0
     */
    @NonNull
    Map<String, Object> getServiceConfig();

    /**
     * 通知类型枚举
     */
    enum NotificationType {
        INFO,       // 信息通知
        SUCCESS,    // 成功通知
        WARNING,    // 警告通知
        ERROR,      // 错误通知
        URGENT      // 紧急通知
    }

    /**
     * 通知优先级枚举
     */
    enum Priority {
        LOW,        // 低优先级
        NORMAL,     // 普通优先级
        HIGH,       // 高优先级
        URGENT      // 紧急优先级
    }

    /**
     * 通知内容类
     */
    class Notification {
        private final String recipient;
        private final String title;
        private final String content;
        private final NotificationType type;
        private final Priority priority;
        private final Map<String, Object> metadata;
        private final long scheduledTime;

        public Notification(String recipient, String title, String content, 
                          NotificationType type, Priority priority) {
            this.recipient = recipient;
            this.title = title;
            this.content = content;
            this.type = type;
            this.priority = priority;
            this.metadata = null;
            this.scheduledTime = 0;
        }

        public Notification(String recipient, String title, String content, 
                          NotificationType type, Priority priority, 
                          Map<String, Object> metadata, long scheduledTime) {
            this.recipient = recipient;
            this.title = title;
            this.content = content;
            this.type = type;
            this.priority = priority;
            this.metadata = metadata;
            this.scheduledTime = scheduledTime;
        }

        // Getters
        public String getRecipient() { return recipient; }
        public String getTitle() { return title; }
        public String getContent() { return content; }
        public NotificationType getType() { return type; }
        public Priority getPriority() { return priority; }
        public Map<String, Object> getMetadata() { return metadata; }
        public long getScheduledTime() { return scheduledTime; }
    }

    /**
     * 发送结果类
     */
    class SendResult {
        private final boolean success;
        private final String messageId;
        private final String message;
        private final String errorCode;
        private final long timestamp;

        public SendResult(boolean success, String messageId, String message) {
            this.success = success;
            this.messageId = messageId;
            this.message = message;
            this.errorCode = success ? null : "SEND_ERROR";
            this.timestamp = System.currentTimeMillis();
        }

        public SendResult(boolean success, String messageId, String message, String errorCode) {
            this.success = success;
            this.messageId = messageId;
            this.message = message;
            this.errorCode = errorCode;
            this.timestamp = System.currentTimeMillis();
        }

        // Getters
        public boolean isSuccess() { return success; }
        public String getMessageId() { return messageId; }
        public String getMessage() { return message; }
        public String getErrorCode() { return errorCode; }
        public long getTimestamp() { return timestamp; }
    }

    /**
     * 批量发送结果类
     */
    class BatchSendResult {
        private final int totalCount;
        private final int successCount;
        private final int failureCount;
        private final List<SendResult> results;
        private final long timestamp;

        public BatchSendResult(int totalCount, int successCount, int failureCount, 
                             List<SendResult> results) {
            this.totalCount = totalCount;
            this.successCount = successCount;
            this.failureCount = failureCount;
            this.results = results;
            this.timestamp = System.currentTimeMillis();
        }

        // Getters
        public int getTotalCount() { return totalCount; }
        public int getSuccessCount() { return successCount; }
        public int getFailureCount() { return failureCount; }
        public List<SendResult> getResults() { return results; }
        public long getTimestamp() { return timestamp; }
        public double getSuccessRate() { 
            return totalCount > 0 ? (double) successCount / totalCount : 0.0; 
        }
    }

    /**
     * 发送状态类
     */
    class SendStatus {
        private final String messageId;
        private final DeliveryStatus status;
        private final String recipient;
        private final long sentTime;
        private final long deliveredTime;
        private final String failureReason;

        public SendStatus(String messageId, DeliveryStatus status, String recipient, 
                        long sentTime, long deliveredTime, String failureReason) {
            this.messageId = messageId;
            this.status = status;
            this.recipient = recipient;
            this.sentTime = sentTime;
            this.deliveredTime = deliveredTime;
            this.failureReason = failureReason;
        }

        // Getters
        public String getMessageId() { return messageId; }
        public DeliveryStatus getStatus() { return status; }
        public String getRecipient() { return recipient; }
        public long getSentTime() { return sentTime; }
        public long getDeliveredTime() { return deliveredTime; }
        public String getFailureReason() { return failureReason; }

        /**
         * 投递状态枚举
         */
        public enum DeliveryStatus {
            PENDING,    // 待发送
            SENT,       // 已发送
            DELIVERED,  // 已投递
            READ,       // 已读取
            FAILED,     // 发送失败
            RECALLED    // 已撤回
        }
    }

    /**
     * 通知异常类
     */
    class NotificationException extends Exception {
        
        private final String errorCode;
        
        public NotificationException(String message) {
            super(message);
            this.errorCode = "NOTIFICATION_ERROR";
        }
        
        public NotificationException(String message, Throwable cause) {
            super(message, cause);
            this.errorCode = "NOTIFICATION_ERROR";
        }
        
        public NotificationException(String errorCode, String message) {
            super(message);
            this.errorCode = errorCode;
        }
        
        public NotificationException(String errorCode, String message, Throwable cause) {
            super(message, cause);
            this.errorCode = errorCode;
        }
        
        public String getErrorCode() {
            return errorCode;
        }
    }
}
